#ifndef __AVR_SPEC__
#define __AVR_SPEC__

#include <iostream>
#include <string>
#include <list>
#include <sstream>

#include "operations.h"

using namespace std;

class AVRSpec
{
public:
  typedef enum {
    None,
    PartNotFound,
    FileFormatError,
    InvalidOption,
    InvalidOptionValue
  } SpecErrorCode;

  AVRSpec (istream& is, const string& part);

  SpecErrorCode error () const { return _errno; }
  int line () const { return _line; }
  int sram_size () const { return _sram_size; }
  int sram_map () const { return _sram_map; }
  int flash_size () const { return _flash_size; }
  int flash_reg_map () const { return _flash_reg_map; }
  list<CoreOperation::OP>::const_iterator ops_begin ()
  { return _ops.begin (); }
  list<CoreOperation::OP>::const_iterator ops_end ()
  { return _ops.end (); }

private:
  SpecErrorCode _errno;
  int _line;
  string _part_name;
  int _sram_size;
  int _sram_map;
  int _flash_size;
  int _flash_reg_map;
  list<CoreOperation::OP> _ops;

  void get_next_line (istream& is, string& str);

  template<class T>
  T get_integral_from_string (const string& str)
  {
    istringstream ss (str);
    T ret;

    if (str[0] == '0' && str[1] == 'x')
      ss >> hex >> ret;
    else
      ss >> ret;

    char f;
    ss >> f;
    if (f== 'k')
      ret *= 1024;

    return ret;
  }

  bool parse_option (const string& opt_line);
};

list<string> string_split (const string& str, char delim);
string string_strip (const string& str);
list<string> string_strip (const list<string>& strs);

#endif /* __AVR_SPEC__ */
